Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
basic-component-mixins
Advanced tools
Mixin library for creating web components in plain JavaScript (ES5 or ES6)
This library implements common web component features as JavaScript mixins. It is designed for people who would like to create web components in plain JavaScript while avoiding much of the boilerplate that comes up in component creation. The mixins permit flexibility and a pay-as-you-go approach to complexity and performance.
Design goals:
All of the top-level Basic Web Components are constructed with these mixins. In fact, by design, most of those components are little more than combinations of mixins. That factoring allows you to create your own web components in the likely event that your needs differ from those driving the design of the Basic Web Components. You can use these mixins without using those components.
The mixins in this library all take the form of a function. Each function takes a base class and returns a subclass defining the desired features:
let MyMixin = (base) => class MyMixin extends base {
// Mixin defines properties and methods here.
greet() {
return "Hello";
}
};
class MyBaseClass {}
let NewClass = MyMixin(MyBaseClass);
let obj = new NewClass();
obj.greet(); // "Hello"
Many JavaScript mixin implementations destructively modify a class prototype, but mixins of the functional style shown above do not. Rather, functional mixins extend the prototype chain and return a new class. Such functions have been called "higher-order components", but we prefer the term "mixin" for brevity.
The mixins in this package take care to ensure that base class properties and methods are not broken by the mixin. In particular, if a mixin wants to add a new property or method, it also invokes the base class' property or method. To do that consistently, these mixins follow standardized [Composition Rules](Composition Rules.md). If you are interested in creating your own component mixins, you may find it helpful to follow those guidelines to ensure that your mixins can interoperate cleanly with the ones in this package.
A core virtue of a functional mixin is that you do not need to use any library to apply it. This lets you use these mixins with any conventional means of defining JavaScript classes — you don't have to invoke a proprietary class factory, nor do you have to load a separate framework or runtime.
Because mixins define behavior through composition, you're not limited by the constraints of a single-inheritance class hierarchy. That said, you can still use a class hierarchy if you feel that's suitable for your application. For example, you can compose a set of mixins to create a custom base class from which your other classes derive. But the use of such a base class is not dictated here.
In a number of areas, this package factors high-level component services into mixins that work together to deliver the overall service. This is done to increase flexibility.
For example, this library includes three mixins that work in concert. When applied to a custom element, these mixins take care of mapping presses on keyboard arrows (Left/Right) into selection actions (select previous/next). They each take care of a different piece of the problem:
keydown
method. By
default, that method does nothing.keydown
method that maps
Left/Right arrow key presses into calls to methods goLeft
and goRight
,
respectively. By default, those methods do nothing.goLeft
and goRight
methods
which respectively invoke methods selectPrevious
and selectNext
. Again, by
default, those methods do nothing.If all three mixins are applied to a component, then when the user presses, say, the Right arrow key, the following sequence happens:
(keyboard event) → keydown() → goRight() → selectNext()
Other mixins can map selection semantics to user-visible effects, such as highlighting the selected item, ensure the selected item is in view, or do something entirely new which you define.
Such factoring may initially feel overly complex, but permits a critical degree of developer freedom. You might want to handle the keyboard a different way, for example. Or you may want to create a component that handles arrow keypresses for something other than selection, for example. Or you may want to let the user manipulate the selection through other modalities, such as touch gestures, mouse actions, speech commands, etc.
As one example of another mode of user input, the
SwipeDirection mixin maps touch gestures to goLeft
and goRight
method calls. It can therefore be used in combination with the
DirectionSelection mixin above, with the result that swipes will change the
selection:
(touch event) → goRight() → selectNext()
The SwipeDirection and KeyboardDirection mixins are compatible, and can be applied to the same component. Users of that component will be able to change the selection with both touch gestures and the keyboard.
This factoring allows components with radically different presentations to nevertheless share a considerable amount of user interface logic. For example, the basic-carousel and basic-list-box components look very different, but both make use of same mixins to support changing the selection with the keyboard. In fact, nearly all of those components' behavior is defined through shared mixins factored this way.
Add a dependencies
key for basic-component-mixins
in your project's
package.json file. Until native Shadow DOM support is available on all browsers
you want to support, you'll want to include the webcomponents.js
polyfill as well:
{
...
"dependencies": {
"basic-component-mixins": "^0.7",
"webcomponents.js": "^0.7.2"
},
}
Then issue an npm install
as usual.
A sample-component project demonstrates the use of npm to depend on the basic-component-mixins package. It shows the creation of a simple component in both ES6 and ES5.
Your ES6 code can reference the mixin as a function exported by the
corresponding file in this package's /src folder. You then apply the mixin to
the element base class you'd like to use. This can be HTMLElement
, or an
element class of your own creation.
As a very simple example, if you'd like to create a web component that puts the
word "Hello" before its tag contents, you can use the ShadowTemplate mixin. This
will look for a template
property on the component, attach a new Shadow DOM
subtree to the component, then copy the template into the shadow subtree.
import ShadowTemplate from 'basic-component-mixins/src/ShadowTemplate';
// Create a simple custom element that supports a template.
class GreetElement extends ShadowTemplate(HTMLElement) {
get template() {
return `
Hello, <slot></slot>.
`;
}
}
// Register the custom element with the browser.
document.registerElement('greet-element', GreetElement);
Compile this source with your favorite ES6 processor (e.g., Babel), then load the result into a page.
<html>
<head>
<script src="node_modules/webcomponents.js/webcomponents.js"></script>
<script src="greet-element.js"></script>
</head>
<body>
<!-- Hello, world. -->
<greet-element>world</greet-element>
</body>
</html>
This package's /dist folder contains a JavaScript file that defines all the
mixins as globals available via window.Basic
. For example, the ShadowTemplate
mixin shown above is available as window.Basic.ShadowTemplate
.
You can create your custom element class by hand:
// greet-element.js
var GreetElement = Basic.ShadowTemplate(HTMLElement);
GreetElement.prototype.template = 'Hello, <slot></slot>.';
document.registerElement('greet-element', GreetElement);
You can also use Composable mixin to create the class:
// greet-element.js
var GreetElement = Basic.Composable(HTMLElement).compose(
Basic.ShadowTemplate,
{
template: 'Hello, <slot></slot>.'
}
);
document.registerElement('greet-element', GreetElement);
Then load the script defining the element into your page:
<html>
<head>
<script src="node_modules/webcomponents.js/webcomponents.js"></script>
<script src="node_modules/basic-component-mixins/dist/basic-component-mixins.js"></script>
<script src="greet-element.js"></script>
</head>
<body>
<!-- Hello, world. -->
<greet-element>world</greet-element>
</body>
</html>
The /src folder includes the complete set of mixins, each of which address some common web component feature:
foo-bar
attribute references to
camelCase fooBar
property names.The /src folder also defines a handful of helper classes and functions that can be useful in defining web components.
Since web components often include many mixins, a helper mixin called Composable provides syntactic sugar that allows multiple mixins to be applied in a single call. Instead of defining an element like:
class MyElement extends Mixin1(Mixin2(Mixin3(Mixin4(HTMLElement)))) {
...
}
You can write:
class MyElement extends Composable(HTMLElement).compose(
Mixin1,
Mixin2,
Mixin3,
Mixin4
) {
...
}
FAQs
Mixins for creating web components in plain JavaScript.
We found that basic-component-mixins demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.